Skip to content

fix(pd): handle border scalars and CPU tensors - #5832

Open
njzjz-bot wants to merge 5 commits into
deepmodeling:masterfrom
njzjz-bot:fix/paddle-border-op-5627
Open

fix(pd): handle border scalars and CPU tensors#5832
njzjz-bot wants to merge 5 commits into
deepmodeling:masterfrom
njzjz-bot:fix/paddle-border-op-5627

Conversation

@njzjz-bot

@njzjz-bot njzjz-bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Fixes #5627

Summary

  • allocate the host copies of scalar nlocal and nghost with one element instead of sizing them by nswap
  • add a documented local-copy helper that chooses gpuMemcpy only for actual GPU places and uses host memcpy for CPU or host-pinned places
  • use the same place-based dispatch for forward and backward self-swaps
  • add direct Paddle custom-op tests for nswap == 0, CPU self-copy, and the reverse self-swap used by autograd

Why existing tests missed this

The existing Paddle suite did not directly call border_op. Model-level tests therefore did not construct the two boundary conditions that matter here: a valid no-swap invocation where the atom-count scalars still need storage, and a self-swap using CPU data from an operator compiled with CUDA support. Normal multi-rank runs also tend to use tensors on the configured accelerator, hiding the mismatch between CUDA-awareness and actual tensor place.

The new no-swap test passes empty communication arrays with scalar atom counts, while the self-swap test keeps a real LAMMPS-style pointer-valued send list alive and checks both forward data and backward execution on CPU tensors. In a CUDA-enabled CI build, the historical code would route that CPU pointer through device-to-device gpuMemcpy.

Validation

  • built the Paddle 3.4 CPU custom op from source/op/pd/setup.py
  • pytest source/tests/pd/test_border_op.py -q (2 passed, including backward)
  • compiled the full GOOGLE_CUDA + USE_MPI branch with Paddle, CUDA 12.4, and MPI headers using mpicxx -fsyntax-only
  • ruff format .
  • ruff check .
  • clang-format --dry-run --Werror source/op/pd/comm.cc
  • git diff --check

The local Paddle wheel is CPU-only, so runtime execution of the CUDA-enabled custom op is left to CUDA CI; the CUDA/MPI branch was still compiled locally, and the new CPU-place self-swap test is designed to run unchanged in that build.

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

Summary by CodeRabbit

  • Bug Fixes

    • Improved tensor copying for border operations across CPU and GPU memory.
    • Corrected zero-swap handling so outputs remain consistent with inputs.
    • Ensured self-copy operations use the appropriate device behavior and preserve gradients.
    • Improved gradient synchronization and handling for GPU-based operations.
  • Tests

    • Added regression coverage for zero-swap behavior and CPU self-copy execution, including pointer-based transfers, duplicated outputs, and gradient validation.

Store nlocal and nghost in one-element host tensors even when there are no swaps, and select local forward/backward copy primitives from the actual Paddle tensor place. Add direct custom-op regressions because existing Paddle model tests did not exercise nswap == 0 or CPU self-swaps in CUDA-enabled builds.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@dosubot dosubot Bot added the bug label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8733e872-d8f0-40c4-a084-08c87b005747

📥 Commits

Reviewing files that changed from the base of the PR and between d4843dd and d387e4f.

📒 Files selected for processing (2)
  • source/op/pd/comm.cc
  • source/tests/pd/test_border_op.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • source/tests/pd/test_border_op.py

📝 Walkthrough

Walkthrough

The Paddle border operation now stages scalar controls in single-element tensors, selects local-copy operations from tensor placement, and updates backward gradient handling. Tests cover zero swaps and CPU self-copy behavior.

Changes

Paddle border operation fixes

Layer / File(s) Summary
Scalar staging and place-aware local copies
source/op/pd/comm.cc
Adds copy_local_tensor_data, uses {1} tensors for scalar staging, and applies place-aware copying to forward and backward local tensors.
Backward gradient synchronization
source/op/pd/comm.cc
Clears ghost gradients when swaps exist, synchronizes GPU execution, and always copies the temporary gradient into recv_g1_tensor_grad.
Regression coverage
source/tests/pd/test_border_op.py
Adds guarded tests for zero swaps and CPU self-copy results and gradients.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fixes for Paddle border scalar storage and CPU tensor handling.
Linked Issues check ✅ Passed The changes allocate scalar copies with shape {1}, dispatch self-copies by tensor place, and add tests for zero swaps and CPU tensors as required by #5627.
Out of Scope Changes check ✅ Passed The changes remain related to border self-copy handling, scalar storage, and gradient behavior exercised by the added regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/tests/pd/test_border_op.py (1)

44-81: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Incorrect gradient expectation in test.

The backward pass of border_op routes the gradient from the ghost slots back to their owner's local slot. In this test, index 2 (the ghost slot) receives its value from index 1 (the owner).
During result.sum().backward(), the gradient for all elements of result is 1.0. The backward operation accumulates the ghost gradient into the local owner using index_add_. Therefore, the gradient at index 1 should be 1.0 + 1.0 = 2.0, while indices 0 and 2 retain their original gradients of 1.0.

The assertion expects np.ones([3, 2]), which would incorrectly mean all gradients are 1.0, causing the test to fail.

💚 Proposed fix
-    np.testing.assert_array_equal(g1_leaf.grad.numpy(), np.ones([3, 2]))
+    expected_grad = np.ones([3, 2])
+    expected_grad[1] = 2.0
+    np.testing.assert_array_equal(g1_leaf.grad.numpy(), expected_grad)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/tests/pd/test_border_op.py` around lines 44 - 81, Update the gradient
assertion in test_border_op_self_copy_uses_cpu_place to expect accumulated
gradients: index 1 should contain 2.0 in both columns, while indices 0 and 2
remain 1.0. Keep the forward result assertion and backward invocation unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/op/pd/comm.cc`:
- Around line 15-37: Wrap the definition of copy_local_tensor_data in `#if`
defined(GOOGLE_CUDA) || defined(TENSORFLOW_USE_ROCM) and the matching `#endif`,
aligning it with its guarded callers so CPU-only builds do not compile
references to gpuMemcpy or gpuMemcpyDeviceToDevice.

---

Outside diff comments:
In `@source/tests/pd/test_border_op.py`:
- Around line 44-81: Update the gradient assertion in
test_border_op_self_copy_uses_cpu_place to expect accumulated gradients: index 1
should contain 2.0 in both columns, while indices 0 and 2 remain 1.0. Keep the
forward result assertion and backward invocation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 17d433ad-098c-4824-b749-a97e187fecbb

📥 Commits

Reviewing files that changed from the base of the PR and between d798a8a and 00eccf4.

📒 Files selected for processing (2)
  • source/op/pd/comm.cc
  • source/tests/pd/test_border_op.py

Comment thread source/op/pd/comm.cc
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.35%. Comparing base (d798a8a) to head (d387e4f).
⚠️ Report is 85 commits behind head on master.

Files with missing lines Patch % Lines
source/op/pd/comm.cc 0.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5832      +/-   ##
==========================================
+ Coverage   78.57%   79.35%   +0.78%     
==========================================
  Files        1049     1085      +36     
  Lines      120659   126409    +5750     
  Branches     4349     4599     +250     
==========================================
+ Hits        94807   100316    +5509     
- Misses      24288    24438     +150     
- Partials     1564     1655      +91     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixes are correct and this is a well-scoped port — pt/comm.cc does not share either bug (it already reads the scalars with .item() and dispatches the self-copy on is_cuda()), so this is pd catching up rather than an incomplete cross-backend fix. The {1} scalar shape and the phi::is_gpu_place-based copy_local_tensor_data are both right. One coverage note is inline; one out-of-scope parity gap for a follow-up:

pd backward lacks pt's ghost-row gradient zeroing (pre-existing, not this PR's scope). In Border_backward_t, d_local_g1_tensor is initialized as a copy of the incoming gradient (

paddle::Tensor d_local_g1_tensor =
paddle::empty(recv_g1_tensor_grad.shape(), recv_g1_tensor_grad.dtype(),
recv_g1_tensor_grad.place());
d_local_g1_tensor.copy_(recv_g1_tensor_grad.contiguous(),
d_local_g1_tensor.place(), true);
) and the reverse-comm loop only index_adds received gradient into owner rows — nothing zeroes the ghost range. pt/comm.cc does this explicitly (d_local_g1_tensor.slice(0, nlocal, ntotal).zero_()) because otherwise the ghost rows retain the raw incoming dL/dg_out[ghost], which is spurious whenever an exchanged feature is consumed as a genuine per-node leaf downstream (attention node embeddings in dpa2/dpa3, spin). pd and pt have diverged here — worth a separate follow-up (and while there, double-check the plain-CPU-build writeback path of the computed d_local_g1).

Comment thread source/tests/pd/test_border_op.py
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz
njzjz requested a review from wanghan-iapcm August 1, 2026 13:55

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paddle.set_device("cpu") call is the right change and it fixes the half of my point that was fixable in this file -- on a paddlepaddle-gpu build the control and data tensors now land on CPU, so is_gpu_place() returns false and the branch matches the test's name.

The other half turns out to be worse than I described, and I got a detail wrong myself, so let me set it out properly. Inline below.

Approving anyway: the scalar handling and the CPU copy path read correctly, the change is small and self-contained, and the coverage problem is an infrastructure fact rather than something wrong with this diff. But I would not treat the green checks as evidence that this code works.

Comment thread source/tests/pd/test_border_op.py
No CI job currently builds Paddle with CUDA, so the CPU-branch regression
cannot fail in any pipeline. Document that intent in the test.

Coding-Agent: opencode
opencode-Version: 1.18.9
Model: ustc/deepseek-v4-flash
Reasoning-Effort: max

@njzjz-bot njzjz-bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed head d4843dd96cf4f388e348140cb7704af35bf2b689 with three independent full subagent reviews. Two P1 backward-pass defects remain and are documented inline: reverse communication is discarded on most build paths, and the new test asserts the resulting incorrect gradient while ghost-input gradients remain nonzero. Because this PR was opened by the active njzjz-bot account, this is a comment-only review rather than a self-request-changes event.

The quota is about to reset, so I am concentrating the remaining token budget on these reviews.

Coding agent: Codex
Codex version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning effort: xhigh

Comment thread source/op/pd/comm.cc
Comment thread source/tests/pd/test_border_op.py Outdated
njzjz-bot and others added 2 commits August 11, 2026 02:44
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Code scan] Fix Paddle border_op scalar and place handling

3 participants